﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Web;
using System.Xml.Serialization;
using Microsoft.ServiceModel.Web;
using WikeSoft.Global;

namespace WikeSoft.WCFUpload
{
    /// <summary>
    /// 通过WCF,上传文件的服务
    /// </summary>
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class FileService
    {
        #region wcf上传文件
        [WebInvoke(UriTemplate = "upload", Method = "POST", ResponseFormat = WebMessageFormat.Xml)]
        [OperationContract]
        public string[] Upload(Stream entityStream)
        {
            IFormatter formatter = new BinaryFormatter();
            FileEntity entity = (FileEntity)formatter.Deserialize(entityStream);
            List<string> ret = new List<string>();
            try
            {
                if (entity == null)
                {
                    throw new ApplicationException("FileEntity is null");
                }

                if (entity.Group == null || entity.AppName == null)
                {
                    throw new ApplicationException("FileEntity.AppName or FileEntity.Group is null.");
                }

                if (entity.Contents == null || entity.Contents.Length == 0)
                {
                    throw new ApplicationException("File Length is Zero");
                }

                if (!entity.IsImageFile.HasValue)
                {
                    throw new ApplicationException("FileEntity.IsImageFile must be have value.");
                }
                string rootPath = AppDomain.CurrentDomain.BaseDirectory;
              

                string appPath = rootPath  + entity.AppName;
                string groupPath = appPath +"\\"+  entity.Group+"\\"+DateTime.Now.Year+"\\"+DateTime.Now.Month+"\\"+DateTime.Now.Day;
                if (!Directory.Exists(appPath))
                    Directory.CreateDirectory(appPath);
                if (!Directory.Exists(groupPath))
                    Directory.CreateDirectory(groupPath);
                entity.FileType = entity.FileType.Trim('.');
                if (entity.IsImageFile.Value) //默认为图片文件
                {
                    string srcFileGuid = Guid.NewGuid().ToString();
                    string tempPath = string.Format("{0}\\{1}.{2}", System.IO.Path.GetTempPath().Trim('\\'), srcFileGuid, entity.FileType);
                    string srcfilePath = string.Format("{0}\\{1}.{2}", groupPath, srcFileGuid, entity.FileType);
                    using (FileStream fs = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
                    {
                        fs.Write(entity.Contents, 0, entity.Contents.Length);
                        fs.Close();
                    }

                    System.IO.File.Copy(tempPath, srcfilePath);
                    ret.Add(srcfilePath);


                    if (entity.IsCompressImage)
                    {
                        if (!entity.ZoomOut.HasValue && !entity.CompressHight.HasValue && !entity.CompressWidth.HasValue)
                        {
                            throw new ApplicationException("FileEntity.IsCompressImage为True时，ZoomOut、CompressHight、CompressWidth至少要有一个属性有值");
                        }
                        string thumfilePath = string.Format("{0}\\{1}-{2}.{3}", groupPath, srcFileGuid, "thum", entity.FileType);
                        //等比缩放
                        if (entity.ZoomOut.HasValue)
                        {
                            this.CompressImage(tempPath, entity.ZoomOut.Value, groupPath, String.Format("{0}-{1}.{2}", srcFileGuid, "thum", entity.FileType), entity.FileType);
                        }
                        else if (entity.CompressWidth.HasValue)
                        {
                            this.CompressImageWidth(tempPath, entity.CompressWidth.Value, groupPath, String.Format("{0}-{1}.{2}", srcFileGuid, "thum", entity.FileType), entity.FileType);
                        }
                        else if (entity.CompressHight.HasValue)
                        {
                            this.CompressImageHight(tempPath, entity.CompressHight.Value, groupPath, String.Format("{0}-{1}.{2}", srcFileGuid, "thum", entity.FileType), entity.FileType);
                        }


                        ret.Add(thumfilePath);
                    }
                    //删除临时文件
                    System.IO.File.Delete(tempPath);


                    for (int i = 0; i < ret.Count; i++)
                    {
                        ret[i] = ret[i].Replace(rootPath, "").Replace('\\', '/');
                    }
                }
                else//如果不是图片则直接保存文件
                {
                    string targetFileName = Guid.NewGuid().ToString();
                    string targetPath = string.Format("{0}\\{1}.{2}", groupPath, targetFileName, entity.FileType);
                    using (FileStream fs = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
                    {
                        fs.Write(entity.Contents, 0, entity.Contents.Length);
                        fs.Close();
                    }
                    ret.Add(targetPath);
                    ret[0] = ret[0].Replace(rootPath, "").Replace('\\', '/');
                }
                return ret.ToArray();
            }
            catch (Exception ex)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, ex.Message, null);
            }
        }
        #endregion

        #region 删除文件
        [WebInvoke(UriTemplate = "delete", Method = "POST", ResponseFormat = WebMessageFormat.Xml)]
        [OperationContract]
        public string DeleteFile(Stream entityStream)
        {
            OperateResult result = new OperateResult();
            try
            {
                string rootPath = AppDomain.CurrentDomain.BaseDirectory;
                IFormatter formatter = new BinaryFormatter();
                List<string> urls = (List<string>)formatter.Deserialize(entityStream);

                foreach (var url in urls)
                {
                    var path = string.Format("{0}{1}", rootPath, url.TrimStart('/').Replace('/', '\\'));
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                }
                result.Message = "删除成功";
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Message = ex.Message;
            }
           


            MemoryStream stream = new MemoryStream();
            XmlSerializer xml = new XmlSerializer(typeof(OperateResult));
            //序列化对象  
            xml.Serialize(stream, result);
            stream.Position = 0;
            StreamReader sr = new StreamReader(stream);
            string str = sr.ReadToEnd();

            sr.Dispose();
            stream.Dispose();

            return str;

          
        }

        #endregion

        #region 通过wcf服务将指定的图片，缩放成指定的大小
       /// <summary>
       /// 
       /// </summary>
       /// <returns></returns>
        [WebInvoke(UriTemplate = "Get", Method = "GET")]
        [OperationContract]
        public Stream Get()
        {
            string url = string.Empty;
            int width = 0, height = 0;
            var param = WebOperationContext.Current.IncomingRequest.GetQueryParameters();
            url = param.Get("url");
            width = Convert.ToInt32(param.Get("w"));
            height = Convert.ToInt32(param.Get("h"));
            if (!String.IsNullOrWhiteSpace(url))
            {
                String path = url.Replace("http://images.gardencity.cn", String.Empty);
                string rootPath = ConfigurationManager.AppSettings["file_root_path"];
                path = String.Format("{0}{1}", rootPath, path.Replace('/', '\\'));
                var bit = this.CompressImage(path, width, height);
                MemoryStream ms = new MemoryStream();
                bit.Save(ms, ImageFormat.Jpeg);
                ms.Position = 0;
                WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
                return ms;
            }
            return null;
        }
        #endregion

        /// <summary>
        /// 固定宽度压缩图片，高度自动计算 ，不变形
        /// </summary>
        /// <param name="srcImgFilePath"></param>
        /// <param name="zoomwith"></param>
        /// <param name="saveDirectory"></param>
        /// <param name="saveFileName"></param>
        /// <param name="extention"></param>
        /// <returns></returns>
        private string CompressImageWidth(string srcImgFilePath, int zoomwith, string saveDirectory,
            string saveFileName, string extention)
        {
            //新建一个指定大小的画布
            Bitmap outbmp = null;
            Graphics g = null;
            Image img = null;
            string targetPath = string.Empty;
            try
            {

                ImageFormat imageFmt = this.GetImageFormat(extention);
                img = Image.FromFile(srcImgFilePath);
                int compressWidth = zoomwith;
                int compressHeight = (int)Math.Floor(((double)img.Height / (double)img.Width) * compressWidth);
                //int compressWidth = (int)(img.Width / zoomwith);
               // int compressHeight = (int)(img.Height / zoomwith);
                //新建一个指定大小的画布
                outbmp = new Bitmap(compressWidth, compressHeight);
                g = Graphics.FromImage(outbmp);
                Size newsize = this.GetCompressSize(compressWidth, compressHeight, img.Width, img.Height);
                // 设置画布的描绘质量
                g.CompositingQuality = CompositingQuality.HighQuality;//设置等比缩放质量
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                if (imageFmt == ImageFormat.Png)
                    g.Clear(System.Drawing.Color.Transparent);
                else
                    g.Clear(Color.FromArgb(255, 255, 255, 255));
                g.DrawImage(img, new Rectangle((compressWidth - newsize.Width) / 2, (compressHeight - newsize.Height) / 2, newsize.Width, newsize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);

                //检查目录文件夹是否存在
                this.CreateDiskDirectory(saveDirectory);
                targetPath = System.IO.Path.Combine(saveDirectory, saveFileName);

                //保存到磁盘
                outbmp.Save(targetPath, imageFmt);
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {
                //释放资源
                if (g != null)
                    g.Dispose();
                if (img != null)
                    img.Dispose();
                if (outbmp != null)
                    outbmp.Dispose();
            }
            return targetPath;
        }


        private string CompressImageHight(string srcImgFilePath, int zoomheight, string saveDirectory,
            string saveFileName, string extention)
        {
            //新建一个指定大小的画布
            Bitmap outbmp = null;
            Graphics g = null;
            Image img = null;
            string targetPath = string.Empty;
            try
            {

                ImageFormat imageFmt = this.GetImageFormat(extention);
                img = Image.FromFile(srcImgFilePath);
                int compressHeight = zoomheight;
                int compressWidth = (int)Math.Floor(((double)img.Width / (double)img.Height) * compressHeight);
               
                //int compressWidth = (int)(img.Width / zoomwith);
                // int compressHeight = (int)(img.Height / zoomwith);
                //新建一个指定大小的画布
                outbmp = new Bitmap(compressWidth, compressHeight);
                g = Graphics.FromImage(outbmp);
                Size newsize = this.GetCompressSize(compressWidth, compressHeight, img.Width, img.Height);
                // 设置画布的描绘质量
                g.CompositingQuality = CompositingQuality.HighQuality;//设置等比缩放质量
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                if (imageFmt == ImageFormat.Png)
                    g.Clear(System.Drawing.Color.Transparent);
                else
                    g.Clear(Color.FromArgb(255, 255, 255, 255));
                g.DrawImage(img, new Rectangle((compressWidth - newsize.Width) / 2, (compressHeight - newsize.Height) / 2, newsize.Width, newsize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);

                //检查目录文件夹是否存在
                this.CreateDiskDirectory(saveDirectory);
                targetPath = System.IO.Path.Combine(saveDirectory, saveFileName);

                //保存到磁盘
                outbmp.Save(targetPath, imageFmt);
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {
                //释放资源
                if (g != null)
                    g.Dispose();
                if (img != null)
                    img.Dispose();
                if (outbmp != null)
                    outbmp.Dispose();
            }
            return targetPath;
        }
        #region 等比缩放指定磁盘路径的图片文件

        /// <summary>
        /// 等比缩放指定磁盘路径中的图片
        /// </summary>
        /// <param name="srcImgFilePath">原始图片文件</param>
        /// <param name="zoomOut">压缩比例</param>
        /// <param name="saveDirectory">图片保存路径</param>
        /// <param name="saveFileName">图片保存文件名</param>
        /// <returns></returns>
        private string CompressImage(string srcImgFilePath, double zoomOut, string saveDirectory, string saveFileName, string extention)
        {
            //新建一个指定大小的画布
            Bitmap outbmp = null;
            Graphics g = null;
            Image img = null;
            string targetPath = string.Empty;
            try
            {

                ImageFormat imageFmt = this.GetImageFormat(extention);
                img = Image.FromFile(srcImgFilePath);
                int compressWidth = (int)(img.Width / zoomOut);
                int compressHeight = (int)(img.Height / zoomOut);
                //新建一个指定大小的画布
                outbmp = new Bitmap(compressWidth, compressHeight);
                g = Graphics.FromImage(outbmp);
                Size newsize = this.GetCompressSize(compressWidth, compressHeight, img.Width, img.Height);
                // 设置画布的描绘质量
                g.CompositingQuality = CompositingQuality.HighQuality;//设置等比缩放质量
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                if (imageFmt == ImageFormat.Png)
                    g.Clear(System.Drawing.Color.Transparent);
                else
                    g.Clear(Color.FromArgb(255, 255, 255, 255));
                g.DrawImage(img, new Rectangle((compressWidth - newsize.Width) / 2, (compressHeight - newsize.Height) / 2, newsize.Width, newsize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);

                //检查目录文件夹是否存在
                this.CreateDiskDirectory(saveDirectory);
                targetPath = System.IO.Path.Combine(saveDirectory, saveFileName);

                //保存到磁盘
                outbmp.Save(targetPath, imageFmt);
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {
                //释放资源
                if (g != null)
                    g.Dispose();
                if (img != null)
                    img.Dispose();
                if (outbmp != null)
                    outbmp.Dispose();
            }
            return targetPath;
        }


        /// <summary>
        /// 等比缩放指定磁盘路径中的图片
        /// </summary>
        /// <param name="srcImgFile">原始图片文件</param>
        /// <param name="compressWidth">最终等比缩放的图片宽度,以像素为单位</param>
        /// <param name="compressHeight">最终等比缩放的图片高度,最终等比缩放的图片宽度</param>
        /// <param name="saveFileName">图片保存文件名</param>
        /// <param name="saveDirectory">图片保存目录</param>
        /// <param name="imgFormat">指定按什么格式保存图片</param>
        private Bitmap CompressImage(string srcImgFilePath, int compressWidth, int compressHeight)
        {
            //新建一个指定大小的画布
            Bitmap outbmp = null;
            Graphics g = null;
            Image img = null;
            try
            {
                img = Image.FromFile(srcImgFilePath);
                //新建一个指定大小的画布
                outbmp = new Bitmap(compressWidth, compressHeight);
                g = Graphics.FromImage(outbmp);
                Size newsize = this.GetCompressSize(compressWidth, compressHeight, img.Width, img.Height);
                // 设置画布的描绘质量
                g.CompositingQuality = CompositingQuality.HighQuality;//设置等比缩放质量
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.Clear(System.Drawing.Color.White);
                g.DrawImage(img, new Rectangle((compressWidth - newsize.Width) / 2, (compressHeight - newsize.Height) / 2, newsize.Width, newsize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);

            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {
                //释放资源
                if (g != null)
                    g.Dispose();
                if (img != null)
                    img.Dispose();
            }
            return outbmp;
        }
        /// <summary>
        /// 获取图片等比缩放尺寸
        /// </summary>
        /// <param name="targetWidth">等比缩放的目标宽度</param>
        /// <param name="targetHeight">等比缩放的目标高度</param>
        /// <param name="srcWidth">原始图宽度</param>
        /// <param name="srcHeight">原始图高度</param>
        /// <returns></returns>
        private Size GetCompressSize(int targetWidth, int targetHeight, int srcWidth, int srcHeight)
        {

            double w = 0.0;
            double h = 0.0;
            double sw = Convert.ToDouble(srcWidth);
            double sh = Convert.ToDouble(srcHeight);
            double mw = Convert.ToDouble(targetWidth);
            double mh = Convert.ToDouble(targetHeight);
            if (srcWidth / srcHeight >= targetWidth / targetHeight)
            {
                if (srcWidth > targetWidth)
                {
                    w = targetWidth;
                    h = (srcHeight * targetWidth) / srcWidth;
                }
                else
                {
                    w = srcWidth;
                    h = srcHeight;
                }
            }
            else
            {
                if (srcHeight > targetHeight)
                {
                    h = targetHeight;
                    w = (srcWidth * targetHeight) / srcHeight;
                }
                else
                {
                    w = srcWidth;
                    h = srcHeight;
                }
            }
            Size size = new Size(Convert.ToInt32(w), Convert.ToInt32(h));
            return size;
        }
        /// <summary>
        /// 检查目录文件夹是否存在
        /// </summary>
        /// <param name="path"></param>
        private void CreateDiskDirectory(string path)
        {
            if (!System.IO.Directory.Exists(path))
                System.IO.Directory.CreateDirectory(path);
            System.IO.DirectoryInfo de = new System.IO.DirectoryInfo(path);
            if ((de.Attributes & System.IO.FileAttributes.ReadOnly) != 0)
                de.Attributes = System.IO.FileAttributes.Normal;
        }
        /// <summary>
        /// 根据webconfig中的配置获取图片保存格式
        /// 如果没有配置则返回ImageFormat.Jpeg
        /// </summary>
        public ImageFormat GetImageFormat(String extention)
        {
            extention = extention.StartsWith(".") ? extention : "." + extention;
            switch (extention)
            {
                case ".gif":
                    return ImageFormat.Gif;
                case ".png":
                    return ImageFormat.Png;
                case ".icon":
                    return ImageFormat.Icon;
                case ".bmp":
                    return ImageFormat.Bmp;
                default:
                    return ImageFormat.Jpeg;
            }
        }
        #endregion
    }
}